﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace iStudio.Structure.Wave
{
    public sealed class WaveChunk : INotifyPropertyChanged
    {
        #region Fields

        private readonly WaveCollection<float> _waveBuffer;
        private bool _isSelected;
        private int _offset;
        private int _channel;

        #endregion

        #region Constructors

        public WaveChunk (int channel)
        {
            Channel = channel;

            _waveBuffer = new WaveCollection<float>();
        }

        public WaveChunk (int channel, long length) : this (channel)
        {
            _waveBuffer = new WaveCollection<float> (new float[length]);
        }

        public WaveChunk (int channel, IEnumerable<float> buffer)
        {
            Channel = channel;

            _waveBuffer = new WaveCollection<float> (buffer);
        }

        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Change info
        /// </summary>
        /// <param name="info"></param>
        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion

        #region Public properties

        /// <summary>
        /// Offset in samples of current chunk
        /// </summary>
        public int Offset
        {
            get
            {
                return _offset;
            }
            set
            {
                if (_offset != value)
                {
                    _offset = value;
                    NotifyPropertyChanged ("Offset");
                }
            }
        }

        /// <summary>
        /// Length in samples of current chunk
        /// </summary>
        public int Length
        {
            get
            {
                return _waveBuffer.Count;
            }
        }

        /// <summary>
        /// Chunk is selected by user
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    NotifyPropertyChanged ("IsSelected");
                }
            }
        }

        /// <summary>
        /// Number of channel of the chunk
        /// </summary>
        public int Channel
        {
            get
            {
                return _channel;
            }
            set
            {
                if (_channel != value)
                {
                    _channel = value;
                    NotifyPropertyChanged ("Channel");
                }
            }
        }

        /// <summary>
        /// Raw samples
        /// </summary>
        public WaveCollection<float> WaveBuffer
        {
            get
            {
                return _waveBuffer;
            }
            set
            {
                //
                // Not create new collection, but will replace samples
                //

                _waveBuffer.SetFrameChange (128);

                for (int i = 0; i < Math.Min(value.Count, _waveBuffer.Count); i++)
                {
                    _waveBuffer[i] = value[i];
                }

                _waveBuffer.SetFrameChange(0);

                // If it is shorter, remove the rest
                if (value.Count <= _waveBuffer.Count)
                {
                    // Remove the rest
                    while (_waveBuffer.Count > value.Count)
                    {
                        _waveBuffer.RemoveAt (_waveBuffer.Count - 1);
                    }
                }
                // if it is longer, add the rest
                else
                {
                    for (int i = _waveBuffer.Count; i < value.Count; i++)
                    {
                        _waveBuffer.Add (value[i]);
                    }
                }

                _waveBuffer.SetFrameChange (0);
            }
        }

        #endregion
    }
}
